
`include "common_header.verilog"

//  *************************************************************************
//  File : p8264_marker_sm_top.vhd
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited.
//  Copyright (c) 2008 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Denis Poverennyy
//  info@morethanip.com
//  *************************************************************************
//  Description : Marker State Machine Top includes 4 instances of Marker
//  Detect Block, each of them handling Marker Detection per Lane.
//  
//  Version     : $Id: p8264_marker_sm_top.v,v 1.4 2017/04/20 18:37:52 wt Exp $
//  *************************************************************************

module p8264_marker_sm_top (

        reset,
        clk,
        mld_rst,
        desk_buff_data_0,
        desk_buff_data_1,
        desk_buff_data_2,
        desk_buff_data_3,
        desk_buff_data_val,
        desk_buf_marker_dval,
        vl_0_enc,
        vl_1_enc,
        vl_2_enc,
        vl_3_enc,
        block_lock,
        align_done,
        align_done_l,
        align_lost_comb,
        vl_map_0,
        vl_map_1,
        vl_map_2,
        vl_map_3        
`ifdef MTIPPCS82_EEE_ENA 
        ,
        ram_period,
        first_rx_lpi_active
`endif   
                        );


input           reset;                  // async active high reset
input           clk;                    // system clock
input           mld_rst;                // VL detection failure or sw reset
input   [65:0]  desk_buff_data_0;       // Data input
input   [65:0]  desk_buff_data_1;       // Data input
input   [65:0]  desk_buff_data_2;       // Data input
input   [65:0]  desk_buff_data_3;       // Data input
input           desk_buff_data_val;     // data from the Deskew buffer are valid
input           desk_buf_marker_dval;   // current block is a marker
input   [23:0]  vl_0_enc;               // Marker pattern for PCS Virtual Lane 0
input   [23:0]  vl_1_enc;               // Marker pattern for PCS Virtual Lane 1
input   [23:0]  vl_2_enc;               // Marker pattern for PCS Virtual Lane 2
input   [23:0]  vl_3_enc;               // Marker pattern for PCS Virtual Lane 3
input   [3:0]   block_lock;             // Block Lock status from all lanes
output          align_done;             // alignment done for all lanes 
output   [3:0]  align_done_l;           // alignment done per lane
output          align_lost_comb;        // at least for one lane Alignment was lost (combined for all lanes)
output   [3:0]  vl_map_0;               // one hot coding for mapping between virtual lane 0 and physical one      
output   [3:0]  vl_map_1;               // one hot coding for mapping between virtual lane 1 and physical one 
output   [3:0]  vl_map_2;               // one hot coding for mapping between virtual lane 2 and physical one 
output   [3:0]  vl_map_3;               // one hot coding for mapping between virtual lane 3 and physical one 

`ifdef MTIPPCS82_EEE_ENA 
input           ram_period;             // if set the RAM is expected;
input           first_rx_lpi_active;    // Boolean variable, first_rx_lpi_active is set true when the receiver is in state RX_LPI_ACTIVE in
                                        // the LPI receive state diagram and R_TYPE(rx_coded) = LI and is otherwise false.
`endif

//-------------------------------------
// Output Signals
//-------------------------------------

reg             align_done;             
reg      [3:0]  align_done_l;           
reg             align_lost_comb;        
wire     [3:0]  vl_map_0;               
wire     [3:0]  vl_map_1;               
wire     [3:0]  vl_map_2;               
wire     [3:0]  vl_map_3;               



//-------------------------------------
// Internal Signals
//-------------------------------------


wire    [3:0]   align_lost;             // AM lost per lane 
wire    [15:0]  vl_map_int;             // Concatenated mapping for all lanes 
reg     [3:0]   vl_map_comb;            // each bit corresponds detected lane
wire    [3:0]   align_done_lane;        // Align done per lane
wire    [3:0]   missed_am;              // No align marker at expected time
                                        // before alignment donereg     
reg             missed_am_comb;         // Combined missed AM 
wire    [66*4 - 1:0]    desk_buff_data; // Concatenated Data input
reg             marker_dval_r;          // current block is a marker (one clock delayed pulse) 
reg             marker_dval_r2;         // current block is a marker (two clocks delayed pulse) 





//  Glue Logic to generate combined status based signals from lanes

always @(posedge clk or posedge reset)
begin
        if (reset == 1'b 1)
        begin
                align_lost_comb <= 1'b 0;	
        end
        else
        begin
                align_lost_comb <= (|align_lost) | missed_am_comb;	
        end
end

always @(posedge clk or posedge reset)
begin 
        if (reset == 1'b 1)
        begin
                missed_am_comb <= 1'b 0;	
        end
        else
        begin
                missed_am_comb <= |missed_am;	
        end
end


//  Combined align done (check that each lanes has an unique marker 
always @(posedge clk or posedge reset)
begin
        if (reset == 1'b 1)
        begin
                vl_map_comb <= {4{1'b 0}};	
        end
        else
        begin
                vl_map_comb <= vl_map_0 | vl_map_1 | vl_map_2 | vl_map_3;	
        end
end



always @(posedge clk or posedge reset)
begin
        if (reset == 1'b 1)
        begin
                align_done <= 1'b 0;	
        end
        else
        begin
                align_done <= (&vl_map_comb) & (&align_done_lane);      
        end
end



//  Align done per lane

always @(posedge clk or posedge reset)
begin
        if (reset == 1'b 1)
        begin
                align_done_l <= {4{1'b 0}};	
        end
        else
        begin
                align_done_l <= {align_done_lane[3], align_done_lane[2], align_done_lane[1], align_done_lane[0]};	
        end
end



always @(posedge clk or posedge reset)
begin
        if (reset == 1'b 1)
        begin
                marker_dval_r   <= 1'b0;
                marker_dval_r2  <= 1'b0;
        end
        else
        begin
                if( block_lock == 4'b 1111 )
                begin
                        marker_dval_r   <= desk_buf_marker_dval;
                        marker_dval_r2  <= marker_dval_r;	
                end
                else
                begin
                        marker_dval_r   <= 1'b 0;
                        marker_dval_r2  <= 1'b 0;
                end
        end
end


assign desk_buff_data = {desk_buff_data_3, desk_buff_data_2, desk_buff_data_1, desk_buff_data_0};



genvar gi;
generate for(gi=0; gi< 4; gi=gi+1)
begin:genfifo
        
p8264_marker_detect U_MARKER_DETECT (

        .reset                  (reset),
        .clk                    (clk),
        .marker_dval_r          (marker_dval_r),
        .marker_dval_r2         (marker_dval_r2),
        .vl_0_enc_in            (vl_0_enc),
        .vl_1_enc_in            (vl_1_enc),
        .vl_2_enc_in            (vl_2_enc),        
        .vl_3_enc_in            (vl_3_enc),  
        .vl_fault               (mld_rst),
        .data_in                (desk_buff_data[gi * 66 + 66-1:gi * 66 +2]),    // [65:2]
        .sh_in                  (desk_buff_data[gi * 66 + 1:gi * 66]),          // [1:0]
        .missed_am              (missed_am[gi]),
        .align_done             (align_done_lane[gi]),
        .vl_map                 (vl_map_int[gi * 4 + 4 -1 :gi * 4]),            // [3:0]
`ifdef MTIPPCS82_EEE_ENA 
        .first_rx_lpi_active    (first_rx_lpi_active),
        .ram_period             (ram_period), 
`endif
        .align_lost             (align_lost[gi]) );
end
endgenerate

assign  {vl_map_3, vl_map_2, vl_map_1, vl_map_0} = vl_map_int;


endmodule // module p8264_marker_sm_top